#!/usr/bin/python
# coding=utf-8
import sys

# 行处理函数
def line_split(line):
    list1 = line.split('#')      # 分离注释
    list2 = list1[0].split('=')  # 分离默认值
    name = list2[0].replace('\n', '')  # 去掉换行符
    name = name.replace(' ', '')   # 去掉空格
    value = ''
    if len(list2) > 1:  # 有默认值
        value = list2[1].replace(' ', '')
    comment = ""
    if len(list1) > 1:
        comment += "   //" + list1[1].replace('\n', '')
    return name, value, comment

# 程序开始
obj_path = sys.argv[1]
# 打开register.h
fpw = open(obj_path + "\\RegistersX.cs", 'w+')
# 清空
fpw.truncate()
# 写入注释头
fpw.write("\
/*---------------------------------------------------------------------\n\
 * File name: RegistersX.cs\n\
 *\n\
 * Copyright (c) <2020-2022>, <ChenLong>\n\
 *\n\
 * All rights reserved.\n\
 *\n\
 * Author: ChenLong\n\
 * Email: worldlong@foxmail.com\n\
 *--------------------------------------------------------------------*/\n")
fpw.write("using System;\n")
fpw.write("\
/*\n\
All registers are 16 bits.\n\
*/\n")
fpw.write("namespace RegistersX\n{\n")
fpw.write("\tstatic class Registers\n\t{\n")

# 读取定义文件
fpr = open(obj_path + "\\registers.def", 'r', encoding='utf-8')
reg_addr = 0
reg_type_name = " "
bit_mask_name = " "
bit_mask_index = 0
nvd_reg_start = -1
nvd_reg_end = -1

for line in fpr.readlines():
    if line.startswith("#"):  # 生成注释
        fpw.write(line.replace("#", "\t\t//"))
    elif line.startswith("\n"):  # 直接换行
        fpw.write(line)
    elif not line.startswith(" "):  # 开头不能有空格
        name, value, comment = line_split(line)
        if name.startswith("NVD_REG_START"):
            nvd_reg_start = reg_addr
        elif name.startswith("NVD_REG_END"):
            nvd_reg_end = reg_addr
        elif name.startswith("REG"):  # 寄存器地址定义，为了保持格式统一，请最后定义寄存器地址
            name_list = name.split("_")
            new_type_name = name_list[1]
            if not new_type_name.startswith(reg_type_name):  # 新的寄存器组
                if len(reg_type_name) > 0 and reg_addr > 0:
                    fpw.write("\t\tpublic static ushort " + reg_type_name + "_REG_END = " + str(reg_addr - 1) + ";" + comment + "\n")
                fpw.write("\t\t//new register group\n")
                if len(new_type_name) > 0:
                    fpw.write("\t\tpublic static ushort " + new_type_name + "_REG_START = " + str(reg_addr) + ";" + comment + "\n")
                reg_type_name = new_type_name
            fpw.write("\t\tpublic static ushort " + name + " = " + str(reg_addr) + ";" + comment + "\n")
            reg_addr += 1
        else:
            if not name.startswith(bit_mask_name):  # 新的bit mask组
                name_list = name.split("_")
                bit_mask_name = name_list[0]
                bit_mask_index = 0
            fpw.write("\t\tpublic static uint " + name + " = (uint)1 << " + str(bit_mask_index) + ";" + comment + "\n")
            bit_mask_index += 1
fpw.write("\t\tpublic static ushort " + reg_type_name + "_REG_END = " + str(reg_addr - 1) + ";\n")
fpw.write("\n")
fpw.write("\t\tpublic static ushort REG_NUMBER = %d;\n" % reg_addr)
if nvd_reg_end >= 0:
    fpw.write("\t\tpublic static ushort NVD_REG_START = %d;\n" % nvd_reg_start)
    fpw.write("\t\tpublic static ushort NVD_REG_END = %d;\n" % nvd_reg_end)
    fpw.write("\t\tpublic static ushort NVD_REG_NUMBER = %d;\n" % (nvd_reg_end - nvd_reg_start))
fpw.write("\n")
fpw.write("\t\tpublic static ushort[] regTable = new ushort[REG_NUMBER];\n")

fpw.write("\t\t/*\n\t\t*/\n")
fpw.write("\
\t\tpublic static void SetAll(ushort val)\n\
\t\t{\n\
\t\t\tfor(int i = 0; i < REG_NUMBER; i++)\n\
\t\t\t{\n\
\t\t\t\tregTable[i] = val;\n\
\t\t\t}\n\
\t\t}\n")

fpw.write("\t\t/*\n\t\t*/\n")
fpw.write("\
\t\tpublic static ushort Reg16Read(int addr)\n\
\t\t{\n\
\t\t\treturn regTable[addr];\n\
\t\t}\n")

fpw.write("\t\t/*\n\t\t*/\n")
fpw.write("\
\t\tpublic static uint Reg32Read(int addr)\n\
\t\t{\n\
\t\t\treturn ((uint)regTable[addr + 1] << 16) + (uint)regTable[addr];\n\
\t\t}\n")

fpw.write("\t\t/*\n\t\t*/\n")
fpw.write("\
\t\tpublic static UInt64 Reg64Read(int addr)\n\
\t\t{\n\
\t\t\treturn ((UInt64)regTable[addr + 3] << 48) +\n\
\t\t\t       ((UInt64)regTable[addr + 2] << 32) +\n\
\t\t\t       ((UInt64)regTable[addr + 1] << 16) +\n\
\t\t\t        (UInt64)regTable[addr];\n\
\t\t}\n")

fpw.write("\t\t/*\n\t\t*/\n")
fpw.write("\
\t\tpublic static void Reg16Write(int addr, ushort data)\n\
\t\t{\n\
\t\t\tregTable[addr] = data;\n\
\t\t}\n")

fpw.write("\t\t/*\n\t\t*/\n")
fpw.write("\
\t\tpublic static void Reg32Write(int addr, uint data)\n\
\t\t{\n\
\t\t\tregTable[addr] = (ushort)data;\n\
\t\t\tregTable[addr + 1] = (ushort)(data >> 16);\n\
\t\t}\n")

fpw.write("\t\t/*\n\t\t*/\n")
fpw.write("\
\t\tpublic static void Reg64Write(int addr, UInt64 data)\n\
\t\t{\n\
\t\t\tregTable[addr] = (ushort)data;\n\
\t\t\tregTable[addr + 1] = (ushort)(data >> 16);\n\
\t\t\tregTable[addr + 2] = (ushort)(data >> 32);\n\
\t\t\tregTable[addr + 3] = (ushort)(data >> 48);\n\
\t\t}\n")

fpw.write("\t}\n")
fpw.write("}\n")
fpr.close()
fpw.close()
